package com.shiyiwei.test.study.transaction.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;

/**
 * @Title: TransactionService
 * @Package: com.shiyiwei.test.study.transaction.service
 * @Description:
 * @author: shiyiwei
 * @date: 2022-01-05 17:35
 * @version: V1.0
 */
@Service
public class TransactionService {

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Autowired
    PlatformTransactionManager platformTransactionManager;

    /**
     * 编程式事务
     * DefaultTransactionDefinition 事务定义，定义一个事务，可以设置事务的传播属性，隔离级别，超时时间等
     * TransactionStatus 事务本身，事务的状态
     * PlatformTransactionManager 事务管理标准，提供接口，不同的厂商有不同的实现比如：JtaTransactionManager,DataSourceTransactionManager
     * 都是他的实现类，其它厂商都是实现了这个接口。
     * 这就是 Spring 中支持事务的三大基础设施。
     */
    public void transfer() {
        //事务定义
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        //事务本身
        TransactionStatus status = platformTransactionManager.getTransaction(definition);

        try {
            jdbcTemplate.update("update account set balance=balance+100 where name ='lilei'");
//            int i = 1 / 0;
            jdbcTemplate.update("update account set balance=balance-100 where name ='hanmeimei'");
            //事务管理器
            platformTransactionManager.commit(status);
        } catch (DataAccessException e) {
            e.printStackTrace();
            platformTransactionManager.rollback(status);
        }
    }

    /**
     * 测试aop处理声明式事务
     * com.shiyiwei.test.study.transaction.config.TransactionManagerConfig类配置了aop全局事务
     * aop的execution 配置了aop事务的执行范围，txMap设置了哪些方法通过aop执行事务.
     */
    public void addAccount() {
        jdbcTemplate.update("update account set balance=balance+100 where name ='lilei'");
//        int i = 1 / 0;
        jdbcTemplate.update("update account set balance=balance-100 where name ='hanmeimei'");
    }

    /**
     * 通过注解的方式使用事务
     */
    @Transactional
    public void testTransactional() {
        jdbcTemplate.update("update account set balance=balance+100 where name ='lilei'");
        int i = 1 / 0;
        jdbcTemplate.update("update account set balance=balance-100 where name ='hanmeimei'");
    }
}
